package com.peking.donations.plugins.pay.wx.service;

import com.google.common.base.Strings;
import com.peking.donations.base.service.BizServiceException;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.peking.donations.base.util.EncryptUtil;
import com.peking.donations.base.util.RandomUtil;
import com.peking.donations.plugins.pay.wx.constants.CacheNames;
import com.peking.donations.plugins.pay.wx.constants.WxAPI;
import com.peking.donations.plugins.pay.wx.utils.Configure;
import com.peking.donations.plugins.pay.wx.utils.GlobalConfigure;
import com.peking.donations.plugins.pay.wx.utils.WxpayException;

/**
 * Created by YGR on 16/3/17.
 */
@Service
public class AuthorizeService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    CacheManager cacheManager;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    Configure configure;

    @Autowired
    GlobalConfigure globalConfigure;

    @Value("${spring.profiles.active}")
    String profile;

    /**
     * 刷新 access_token
     * 
     * @throws WxpayException
     */
    public void refreshAccessToken() throws WxpayException {
        String url = String.format(WxAPI.ACCESS_TOKEN.getApi(), configure.getAppID(), configure.getSecret());
        ResponseEntity<JSONObject> forEntity = restTemplate.getForEntity(url, JSONObject.class);
        JSONObject body = forEntity.getBody();
        Object accessToken = body.get("access_token");
        if (null != accessToken) {
            cacheManager.getCache(CacheNames.WX_ACCESS_TOKEN.name()).put(configure.getAppID(), accessToken);
        } else {
            throw new WxpayException("获取access_token 失败!返回值[" + body.toString() + "]");
        }
    }

    /**
     * 刷新 jsapi_ticket
     * 
     * @throws WxpayException
     */
    public void refreshJSTicket() throws WxpayException {
        String accessToken = getAccessToken(configure.getAppID());
        String url = String.format(WxAPI.JSAPI_TICKET.getApi(), accessToken);
        ResponseEntity<JSONObject> entity = restTemplate.getForEntity(url, JSONObject.class);
        JSONObject jsTicketResponse = entity.getBody();
        logger.debug("jsTicketResponse:{}", jsTicketResponse.toString());
        Object ticket = jsTicketResponse.get("ticket");
        if (null == ticket) {
            throw new WxpayException("jsTicket 失败!返回值[" + jsTicketResponse.toString() + "]");
        } else {
            cacheManager.getCache(CacheNames.WX_JS_API_TICKET.name()).put(configure.getAppID(), ticket);
        }
    }

    /**
     * 获取 access_token
     * 
     * @param appId
     * @return
     */
    public String getAccessToken(String appId) {
        Cache.ValueWrapper valueWrapper = cacheManager.getCache(CacheNames.WX_ACCESS_TOKEN.name()).get(appId);
        if (null != valueWrapper) {
            return (String) valueWrapper.get();
        }
        return null;
    }

    /**
     * 获取 jsapi_ticket
     * 
     * @param appId
     * @return
     */
    public String getJsApiTicket(String appId) {
        Cache.ValueWrapper valueWrapper = cacheManager.getCache(CacheNames.WX_JS_API_TICKET.name()).get(appId);
        if (null != valueWrapper) {
            return (String) valueWrapper.get();
        }
        return null;
    }

    public String getThirdJsApiTicket() throws BizServiceException {
        String random = RandomUtil.randStringFixed(6);
        String key = globalConfigure.getEncryptkey() + random + globalConfigure.getEncryptsecret();
        String md5 = EncryptUtil.MD5(key).toLowerCase();

        String url = String.format("http://yanyuan.pku.org.cn/wx/pekingdonation/access_token?nonce=%s&md5=%s", random,
                md5);
        ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class);
        if (null != entity) {
            JSONObject jsonObject = JSONObject.parseObject(entity.getBody());
            System.out.println(jsonObject.toString());
            String access_token = jsonObject.getString("access_token");
            if(Strings.isNullOrEmpty(access_token)){
                throw new BizServiceException("获取access_token失败");
            }
            return jsonObject.getString("jsapi_ticket");
        }
        return null;
    }

    /**
     * 计算并返回jssdk的签名
     *
     * @param url
     * @param timestamp
     * @param nonceStr
     * @return
     */
    public String getJssdkSignature(String appId, String url, String timestamp, String nonceStr) throws BizServiceException {
        String ticket;
        try {
            if ("prod".equals(profile)) {
                ticket = getThirdJsApiTicket();

            } else {
                ticket = getJsApiTicket(appId);
            }
        } catch (Exception e) {
            logger.error("获取jspai ticket 失败!", e);
            throw new BizServiceException("获取jspai ticket 失败");
        }

        String s = String.format("jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s", ticket, nonceStr, timestamp, url);
        logger.debug("signature url={}", s);

        return DigestUtils.sha1Hex(s);
    }

}
